
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;


public class Test {

	public HashMap<String,Integer> argFctPredefinie = new HashMap<String,Integer>();
	
	public HashMap<String,Method> methodFctPredefinie = new HashMap<String,Method>();
	
	
	public Test() {
		argFctPredefinie.put("egal?", 2);
		argFctPredefinie.put("inegal?", 2);
		argFctPredefinie.put("pluspetit?", 2);
		argFctPredefinie.put("plusgrand?", 2);
		argFctPredefinie.put("pluspetitou?", 2);
		argFctPredefinie.put("plusgrandou?", 2);
		argFctPredefinie.put("mot?", 1);
		argFctPredefinie.put("nombre?", 1);
		argFctPredefinie.put("liste?", 1);
		argFctPredefinie.put("vide?", 1);
		argFctPredefinie.put("precede?", 2);
		argFctPredefinie.put("membre?", 2);
		argFctPredefinie.put("et", 2);
		argFctPredefinie.put("ou", 2);
		argFctPredefinie.put("non", 1);
		argFctPredefinie.put("fonction?", 1);
		argFctPredefinie.put("pour?", 1);
		argFctPredefinie.put("primitive?", 1);
		
		
		Class c = Test.class;
		Method[] tab = c.getMethods();
		
		Method  m;
		for (int i=0;i<tab.length;i++) {
			m = tab[i];
			if(m.getName().equals("egalite"))
				methodFctPredefinie.put("egal?", m);			
			if(m.getName().equals("inegalite"))
				methodFctPredefinie.put("inegal?", m);			
			if(m.getName().equals("pluspetit"))
				methodFctPredefinie.put("pluspetit?", m);			
			if(m.getName().equals("plusgrand"))
				methodFctPredefinie.put("plusgrand?", m);
			if(m.getName().equals("pluspetitou"))
				methodFctPredefinie.put("pluspetitou?", m);			
			if(m.getName().equals("plusgrandou"))
				methodFctPredefinie.put("plusgrandou?", m);
			if(m.getName().equals("mot"))
				methodFctPredefinie.put("mot?", m);			
			if(m.getName().equals("nombre"))
				methodFctPredefinie.put("nombre?", m);			
			if(m.getName().equals("liste"))
				methodFctPredefinie.put("liste?", m);			
			if(m.getName().equals("vide"))
				methodFctPredefinie.put("vide?", m);			
			if(m.getName().equals("precede"))
				methodFctPredefinie.put("precede?", m);			
			if(m.getName().equals("membre"))
				methodFctPredefinie.put("membre?", m);			
			if(m.getName().equals("ou"))
				methodFctPredefinie.put("ou", m);			
			if(m.getName().equals("et"))
				methodFctPredefinie.put("et", m);			
			if(m.getName().equals("non"))
				methodFctPredefinie.put("non", m);			
			if(m.getName().equals("fonction"))
				methodFctPredefinie.put("fonction?", m);			
			if(m.getName().equals("pour"))
				methodFctPredefinie.put("pour?", m);			
			if(m.getName().equals("primitive"))
				methodFctPredefinie.put("primitive?", m);
		}    
	}
	
	
	

public static Object egalite(ArrayList<Object> v,  HashMap<String, Object> penv){
		
	
		if(v.size() == 2) {
			if(v.get(0) instanceof Integer) {
				if(v.get(1) instanceof Integer)
					return v.get(0).equals(v.get(1));
				else 
					if(v.get(1) instanceof Double)
						return (int)(Integer)v.get(0) == (Double)v.get(1);
			}	
			else
				if(v.get(0) instanceof Double) {
					if(v.get(1) instanceof Double)
						return v.get(0).equals(v.get(1));
					else 
						if(v.get(1) instanceof Integer)
							return (Double)v.get(0) == (int)(Integer)v.get(1);
				}
			if(v.get(0) instanceof String && v.get(1) instanceof String)
				if (((String)v.get(0)).compareTo((String)v.get(1)) == 0)
					return true;
				else return false;
			else 
				if(v.get(0) instanceof ArrayList && v.get(1) instanceof ArrayList)
					return testlist((ArrayList)v.get(0), (ArrayList)v.get(1));
				else return false;
			}
			
		else return null;
	}
	

private static boolean testlist(ArrayList l1, ArrayList l2){
	int i=0;
	boolean test = true;
	
	if(l1.size() == l2.size()) {
		while(test && i<l2.size()) {
			if(l1.get(i) instanceof ArrayList && l2.get(i) instanceof ArrayList)
				test = testlist((ArrayList)l1.get(i), (ArrayList)l2.get(i));
			else
				test = l1.get(i).equals(l2.get(i));
			i++;
		}
	}
		else return false;
	
	
	return test;
}




public static Object inegalite(ArrayList<Object> v,  HashMap<String, Object> penv){
	
	
	if(v.size() == 2) {
		if(v.get(0) instanceof Integer) {
			if(v.get(1) instanceof Integer)
				return !v.get(0).equals(v.get(1));
			else 
				if(v.get(1) instanceof Double)
					return !((int)(Integer)v.get(0) == (Double)v.get(1));
		}	
		else
			if(v.get(0) instanceof Double) {
				if(v.get(1) instanceof Double)
					return !v.get(0).equals(v.get(1));
				else 
					if(v.get(1) instanceof Integer)
						return !((Double)v.get(0) == (int)(Integer)v.get(1));
			}
		if(v.get(0) instanceof String && v.get(1) instanceof String)
			if (((String)v.get(0)).compareTo((String)v.get(1)) != 0)
				return true;
			else return false;
		else 
			if(v.get(0) instanceof ArrayList && v.get(1) instanceof ArrayList)
				return !testlist((ArrayList)v.get(0), (ArrayList)v.get(1));
			else return true;
		}
		
	else return null;
}


	public static Object pluspetit(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.get(0) instanceof Integer) {
			if(v.get(1) instanceof Integer)
				return (Integer)v.get(0) < (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Double)
					return (int)(Integer)v.get(0) < (Double)v.get(1);
		}
		else
			if(v.get(0) instanceof Double) {
				if(v.get(1) instanceof Double)
					return (Integer)v.get(0) < (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Integer)
					return (Double)v.get(0) < (int)(Integer)v.get(1);
			}
		return null;
	}

	
public static Object pluspetitou(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.get(0) instanceof Integer) {
			if(v.get(1) instanceof Integer)
				return (Integer)v.get(0) <= (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Double)
					return (int)(Integer)v.get(0) <= (Double)v.get(1);
		}
		else
			if(v.get(0) instanceof Double) {
				if(v.get(1) instanceof Double)
					return (Integer)v.get(0) <= (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Integer)
					return (Double)v.get(0) <= (int)(Integer)v.get(1);
			}
		return null;
	}

	public static Object plusgrand(ArrayList<Object> v,  HashMap<String, Object> penv){

		if(v.get(0) instanceof Integer) {
			if(v.get(1) instanceof Integer)
				return (Integer)v.get(0) > (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Double)
					return (int)(Integer)v.get(0) > (Double)v.get(1);
		}
		else
			if(v.get(0) instanceof Double) {
				if(v.get(1) instanceof Double)
					return (Integer)v.get(0) > (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Integer)
					return (Double)v.get(0) > (int)(Integer)v.get(1);
			}
		return null;
	}
	
	
	public static Object plusgrandou(ArrayList<Object> v,  HashMap<String, Object> penv){

		if(v.get(0) instanceof Integer) {
			if(v.get(1) instanceof Integer)
				return (Integer)v.get(0) >= (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Double)
					return (int)(Integer)v.get(0) >= (Double)v.get(1);
		}
		else
			if(v.get(0) instanceof Double) {
				if(v.get(1) instanceof Double)
					return (Integer)v.get(0) >= (Integer)v.get(1);
			else 
				if(v.get(1) instanceof Integer)
					return (Double)v.get(0) >= (int)(Integer)v.get(1);
			}
		return null;
	}
	
	public static Object mot(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 1)
			return v.get(0) instanceof String;
		else return null;
	}
	
	
	public static Object nombre(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 1)
			return (v.get(0) instanceof Integer || v.get(0) instanceof Double);
		else return null;
	}


	public static Object liste(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 1)
			return v.get(0) instanceof ArrayList;
		else return null;
	}
	
	
	public static Object vide(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 1 && v.get(0) instanceof ArrayList)
			return ((ArrayList)v.get(0)).isEmpty();
		else return null;
	}
	
	public static Object precede(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 2 && v.get(0) instanceof String && v.get(1) instanceof String)
			if (((String)v.get(0)).compareTo((String)v.get(1)) < 0 )
					return true;
			else return false;
		else return null;
		
	}
	
	//uniquement sur les liste
	public static Object membre(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.size() == 2 && v.get(0) instanceof ArrayList)
			return ((ArrayList)v.get(0)).contains(v.get(1));
		else return null;
	}
	
	
	public static Object et(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		boolean test = true;
		boolean et = true; 
		int i = 0;
		
		while(test && i < v.size()) {
			if(!(v.get(i) instanceof Boolean))
				test = false;
			else
				et = et && (Boolean)v.get(i);
			
			i++;
		}
		
		if (i == v.size())
			return et;
		else
			return null;
	}
	
	
	public static Object ou(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		boolean test = true;
		boolean ou = false; 
		int i = 0;
		
		while(test && i < v.size()) {
			if(!(v.get(i) instanceof Boolean))
				test = false;
			else
				ou = ou || (Boolean)v.get(i);
			
			i++;
		}
		
		if (i == v.size())
			return ou;
		else
			return null;
	}


	public static Object non(ArrayList<Object> v,  HashMap<String, Object> penv){
	
		if(v.get(0) instanceof Boolean && v.size() == 1)
			return !(Boolean)v.get(0);
		else	
			return null;

	}
	
	
	public static Object fonction(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.get(0) instanceof String && v.size() == 1)
			return Bibliotheque.argFctPredefinie.containsKey((String)v.get(0)) || Bibliotheque.argFctDefinie.containsKey((String)v.get(0));
		else	
			return null;

	}

	
	public static Object primitive(ArrayList<Object> v,  HashMap<String, Object> penv){
		
		if(v.get(0) instanceof String && v.size() == 1)
			return Bibliotheque.argFctPredefinie.containsKey((String)v.get(0));
		else	
			return null;

	}


	public static Object pour(ArrayList<Object> v,  HashMap<String, Object> penv){
	
		if(v.get(0) instanceof String && v.size() == 1)
			return Bibliotheque.argFctDefinie.containsKey((String)v.get(0));
		else	
			return null;

	}
}




